# -*- coding: utf-8 -*-
# created on 2017/5/26
# 

from mathsolver.functions.base import *
from mathsolver.functions.base.base import new_latex
from mathsolver.functions.sanjiao.sanjiao_utils import i_trig_simplify, trig_simped, simp_trig_info
from sympy import sin
from sympy.abc import k, a, b
from mathsolver.functions.daoshu.daoshuyunsuan import HanShuDaoShuYunSuan
from mathsolver.functions.hanshu.hengchengli import HengChengLiRenYiXing


class DanDiaoXingQiuCan001(BaseFunction):
    def solver(self, *args):
        """
        :param args:
            BaseSinFunc({"var": "x", "expression": "sin(omega*x)+sqrt(3)*cos(omega*x)+1", "type": "", "name": "f"})
            BaseInter(["[", "0", "(pi)/(3)", "]"])
            BaseInter(["[", "(pi)/(3)", "(pi)/(2)", "]"])
        :return: BaseEq(eq)
        备注:第一个区间是递增区间，第二个区间是递减区间
        """
        assert len(args) == 3
        sinfunc = args[0].sympify()
        sinfunc_value = sinfunc[1]
        sinfunc_value = i_trig_simplify(sinfunc_value)
        assert trig_simped(sinfunc_value)
        new_f = args[0]
        if str(sinfunc_value) != str(args[0].expression):
            self.steps.append(["", "由三角恒等变换, 得"])
            new_f = BaseSinFunc(
                {"var": args[0].var, "expression": sinfunc_value, "type": args[0].type, "name": args[0].name})
            self.steps.append(["", "%s" % new_f.printing()])
        sinfunc_value_a, sinfunc_value_type, sinfunc_value_inner, sinfunc_value_b = simp_trig_info(sinfunc_value)
        if str(sinfunc_value_type) == str("cos"):
            sinfunc_value = sinfunc_value_a * sin(sinfunc_value_inner + pi / 2) + sinfunc_value_b
            self.steps.append(["", "由诱导公式, 得"])
            new_f = BaseSinFunc(
                {"var": args[0].var, "expression": sinfunc_value, "type": args[0].type, "name": args[0].name})
            self.steps.append(["", "%s" % new_f.printing()])
        sinfunc_value_a, sinfunc_value_type, sinfunc_value_inner, sinfunc_value_b = simp_trig_info(sinfunc_value)
        var = args[0].var
        z_inter = args[1].interval
        j_inter = args[2].interval
        zleft, zright, zlopen, zropen = z_inter.args
        jleft, jright, jlopen, jropen = j_inter.args
        self.steps.append(["", "依题意, 得"])
        if zright == jleft:
            self.steps.append(["", "函数%s在%s=%s处取到最大值" % (new_f.printing(), new_latex(var), new_latex(zright))])
            new_sinfunc_value_inner = sinfunc_value_inner.subs({var: zright})
            eq = [new_sinfunc_value_inner, 2 * k * pi + pi / 2]
            self.steps.append(["", "∴ %s" % BaseEq(eq).printing()])
            self.output.append(BaseEq(eq))
        elif zleft == jright:
            self.steps.append(
                ["", "函数%s在%s=%s处取到最小值" % (args[0].printing(), new_latex(var), new_latex(zright))])
            new_sinfunc_value_inner = sinfunc_value_inner.subs({var: zleft})
            eq = [new_sinfunc_value_inner, 2 * k * pi + 3 * pi / 2]
            self.steps.append(["", "∴ %s" % BaseEq(eq).printing()])
            self.output.append(BaseEq(eq))
        return self


class DanDiaoXingQiuCan002(BaseFunction):
    def solver(self, *args):
        """
        :param args:
            BaseSinFunc({"var": "x", "expression": "sin(2*x+pi/3)+2", "type": "", "name": "f"})
            BaseEq(["f(x_1)*f(x_2)", "9"])
        :return: BaseEqs(eqs)
        """
        assert len(args) == 2
        sinfunc = args[0].sympify()
        sinfunc_value = sinfunc[1]
        sinfunc_value = i_trig_simplify(sinfunc_value)
        assert trig_simped(sinfunc_value)
        var = args[0].var
        if str(sinfunc_value) != str(args[0].expression):
            self.steps.append(["", "由三角恒等变换, 得"])
            new_f = BaseSinFunc(
                {"var": args[0].var, "expression": sinfunc_value, "type": args[0].type, "name": args[0].name})
            self.steps.append(["", "%s" % new_f.printing()])
        sinfunc_value_a, sinfunc_value_type, sinfunc_value_inner, sinfunc_value_b = simp_trig_info(sinfunc_value)
        if str(sinfunc_value_type) == str("cos"):
            sinfunc_value = sinfunc_value_a * sin(sinfunc_value_inner + pi / 2) + sinfunc_value_b
            self.steps.append(["", "由诱导公式, 得"])
            new_f = BaseSinFunc(
                {"var": args[0].var, "expression": sinfunc_value, "type": args[0].type, "name": args[0].name})
            self.steps.append(["", "%s" % new_f.printing()])
        sinfunc_value_a, sinfunc_value_type, sinfunc_value_inner, sinfunc_value_b = simp_trig_info(sinfunc_value)
        assert sinfunc_value_a > 0
        assert sinfunc_value_b >= 0
        eq = args[1].sympify()
        expr = eq[0] - eq[1]
        parts = get_all_child(expr, lambda xx: str(xx.func) == str("f"))
        assert len(parts) == 2
        new_parts = [a, b]
        subs_list = [(xx, yy) for xx, yy in zip(parts, new_parts)]
        new_expr = expr.subs(subs_list)
        self.steps.append(["", "依题意, 得"])
        if str(new_expr).find(str("Abs")) >= 0:
            raise Exception("to do")
        else:
            answer_as = solve(new_expr, a)
            assert len(answer_as) == 1
            answer_a = answer_as[0]
            if (a not in (answer_a * b).free_symbols) and (b not in (answer_a * b).free_symbols) and (
                    sinfunc_value_b != 0):
                eq_right = answer_a * b
                if eq_right - (sinfunc_value_a + sinfunc_value_b) ** 2 == 0:
                    eqs = []
                    i = 1
                    for part in parts:
                        part_var = part.args[0]
                        part_value = sinfunc_value_inner.subs({var: part_var})
                        cof = str("k_") + str(i)
                        cof = sympify(cof)
                        eqs.append([part_value, 2 * cof * pi + pi / 2])
                        i += 1
                    self.steps.append(["", "%s" % BaseEqs(eqs).printing()])
                    self.output.append(BaseEqs(eqs))
            elif (a not in (answer_a - b).free_symbols) and (b not in (answer_a - b).free_symbols) and (
                    sinfunc_value_b != 0):
                eq_right = answer_a - b
                if (eq_right < 0) and (eq_right + 2 * sinfunc_value_a == 0):
                    eqs = []
                    parta_var = parts[0].args[0]
                    parta_value = sinfunc_value_inner.subs({var: parta_var})
                    cofa = str("k_") + str(1)
                    cofa = sympify(cofa)
                    eqs.append([parta_value, 2 * cofa * pi + 3 * pi / 2])

                    partb_var = parts[1].args[0]
                    partb_value = sinfunc_value_inner.subs({var: partb_var})
                    cofb = str("k_") + str(2)
                    cofb = sympify(cofb)
                    eqs.append([partb_value, 2 * cofb * pi + pi / 2])
                    self.steps.append(["", "%s" % BaseEqs(eqs).printing()])
                    self.output.append(BaseEqs(eqs))
                elif (eq_right > 0) and (eq_right - 2 * sinfunc_value_a == 0):
                    eqs = []
                    parta_var = parts[0].args[0]
                    parta_value = sinfunc_value_inner.subs({var: parta_var})
                    cofa = str("k_") + str(1)
                    cofa = sympify(cofa)
                    eqs.append([parta_value, 2 * cofa * pi + pi / 2])

                    partb_var = parts[1].args[0]
                    partb_value = sinfunc_value_inner.subs({var: partb_var})
                    cofb = str("k_") + str(2)
                    cofb = sympify(cofb)
                    eqs.append([partb_value, 2 * cofb * pi + 3 * pi / 2])
                    self.steps.append(["", "%s" % BaseEqs(eqs).printing()])
                    self.output.append(BaseEqs(eqs))
        return self


class DanDiaoXingQiuCan003(BaseFunction):
    def solver(self, *args):
        """
        :param args:
            BaseSinFunc({"var": "x", "expression": "sin(2*x+pi/3)+2", "type": "", "name": "f"})
            BaseSinFunc({"var": "x", "expression": "sin(2*x+pi/6)+2", "type": "", "name": "g"})
            BaseEq(["f(x_1)-g(x_2)", "-2"])
        :return: BaseEqs(eqs)
        """
        assert len(args) == 3
        sinfunc_f_value = sympify(args[0].expression)
        sinfunc_f_value = i_trig_simplify(sinfunc_f_value)
        assert trig_simped(sinfunc_f_value)
        var = args[0].var
        if str(sinfunc_f_value) != str(args[0].expression):
            self.steps.append(["", "由三角恒等变换, 得"])
            new_f = BaseSinFunc(
                {"var": args[0].var, "expression": sinfunc_f_value, "type": args[0].type, "name": args[0].name})
            self.steps.append(["", "%s" % new_f.printing()])
        sinfunc_f_value_a, sinfunc_f_value_type, sinfunc_f_value_inner, sinfunc_f_value_b = simp_trig_info(
            sinfunc_f_value)
        if str(sinfunc_f_value_a) == str("cos"):
            sinfunc_f_value = sinfunc_f_value_a * sin(sinfunc_f_value_inner + pi / 2) + sinfunc_f_value_b
            self.steps.append(["", "由诱导公式, 得"])
            new_f = BaseSinFunc(
                {"var": args[0].var, "expression": sinfunc_f_value, "type": args[0].type, "name": args[0].name})
            self.steps.append(["", "%s" % new_f.printing()])
            sinfunc_f_value_a, sinfunc_f_value_type, sinfunc_f_value_inner, sinfunc_f_value_b = simp_trig_info(
                sinfunc_f_value)

        sinfunc_g_value = sympify(args[1].expression)
        sinfunc_g_value = i_trig_simplify(sinfunc_g_value)
        assert trig_simped(sinfunc_f_value)
        if str(sinfunc_g_value) != str(args[1].expression):
            self.steps.append(["", "由三角恒等变换, 得"])
            new_f = BaseSinFunc(
                {"var": args[0].var, "expression": sinfunc_g_value, "type": args[0].type, "name": args[0].name})
            self.steps.append(["", "%s" % new_f.printing()])
        sinfunc_g_value_a, sinfunc_g_value_type, sinfunc_g_value_inner, sinfunc_g_value_b = simp_trig_info(
            sinfunc_g_value)
        if str(sinfunc_g_value_a) == str("cos"):
            sinfunc_g_value = sinfunc_g_value_a * sin(sinfunc_g_value_inner + pi / 2) + sinfunc_g_value_b
            self.steps.append(["", "由诱导公式, 得"])
            new_g = BaseSinFunc(
                {"var": args[1].var, "expression": sinfunc_g_value, "type": args[1].type, "name": args[1].name})
            self.steps.append(["", "%s" % new_g.printing()])
            sinfunc_g_value_a, sinfunc_g_value_type, sinfunc_g_value_inner, sinfunc_g_value_b = simp_trig_info(
                sinfunc_g_value)
        assert sinfunc_f_value_a - sinfunc_g_value_a == 0
        assert sinfunc_f_value_b - sinfunc_g_value_b == 0
        assert sinfunc_f_value_a > 0
        assert sinfunc_f_value_b > 0
        eq = args[2].sympify()
        expr = eq[0] - eq[1]
        parts = get_all_child(expr, lambda xx: str(xx.func) in [str("f"), str("g")])
        assert len(parts) == 2
        new_parts = [a, b]
        subs_list = [(xx, yy) for xx, yy in zip(parts, new_parts)]
        new_expr = expr.subs(subs_list)
        self.steps.append(["", "依题意, 得"])
        if str(new_expr).find(str("Abs")) >= 0:
            raise Exception("to do")
        else:
            answer_as = solve(new_expr, a)
            assert len(answer_as) == 1
            answer_a = answer_as[0]
            if (a not in (answer_a - b).free_symbols) and (b not in (answer_a - b).free_symbols):
                eq_right = answer_a - b
                if (eq_right < 0) and (eq_right + 2 * sinfunc_f_value_a == 0):
                    eqs = []
                    parta_var = parts[0].args[0]
                    if str(parts[0].func) == args[0].name:
                        parta_value = sinfunc_f_value_inner.subs({var: parta_var})
                    else:
                        parta_value = sinfunc_g_value_inner.subs({var: parta_var})
                    cofa = str("k_") + str(1)
                    cofa = sympify(cofa)
                    eqs.append([parta_value, 2 * cofa * pi + 3 * pi / 2])

                    partb_var = parts[1].args[0]
                    if str(parts[1].func) == args[0].name:
                        partb_value = sinfunc_f_value_inner.subs({var: partb_var})
                    else:
                        partb_value = sinfunc_g_value_inner.subs({var: partb_var})
                    cofb = str("k_") + str(2)
                    cofb = sympify(cofb)
                    eqs.append([partb_value, 2 * cofb * pi + pi / 2])
                    self.steps.append(["", "%s" % BaseEqs(eqs).printing()])
                    self.output.append(BaseEqs(eqs))
                elif (eq_right > 0) and (eq_right - 2 * sinfunc_f_value_a == 0):
                    eqs = []
                    parta_var = parts[0].args[0]
                    if str(parts[0].func) == args[0].name:
                        parta_value = sinfunc_f_value_inner.subs({var: parta_var})
                    else:
                        parta_value = sinfunc_g_value_inner.subs({var: parta_var})
                    cofa = str("k_") + str(1)
                    cofa = sympify(cofa)
                    eqs.append([parta_value, 2 * cofa * pi + pi / 2])

                    partb_var = parts[1].args[0]
                    if str(parts[1].func) == args[0].name:
                        partb_value = sinfunc_f_value_inner.subs({var: partb_var})
                    else:
                        partb_value = sinfunc_g_value_inner.subs({var: partb_var})
                    cofb = str("k_") + str(2)
                    cofb = sympify(cofb)
                    eqs.append([partb_value, 2 * cofb * pi + 3 * pi / 2])
                    self.steps.append(["", "%s" % BaseEqs(eqs).printing()])
                    self.output.append(BaseEqs(eqs))
        return self


class DanDiaoXingQiuCan004(BaseFunction):
    def solver(self, *args):
        """
        :param args:
            BaseSinFunc({"var": "x", "expression": "cos(2*x)+a*sin(x)", "type": "", "name": "f"})
            BaseInter(["(", "(pi)/(6)", "(pi)/(3)", ")"])
        :return: BaseVariable
        备注:第二个为单调递增区间
        """
        assert len(args) == 2
        z_inter = args[1].interval
        self.steps.append(["", "求导,得"])
        stepsolver1 = HanShuDaoShuYunSuan().solver(BaseFunc({"var": args[0].var,
                                                             "name": args[0].name,
                                                             "type": args[0].type,
                                                             "expression": args[0].expression}))
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        daohanshu = stepsolver1.output[0].sympify()
        self.steps.append(["", "∵%s在%s上单调递增" % (args[0].printing(), args[1].printing())])
        ineq = [daohanshu[1], ">=", S.Zero]
        self.steps.append(["", "%s在%s上恒成立" % (BaseIneq(ineq).printing(), args[1].printing())])
        stepsolver2 = HengChengLiRenYiXing().solver(BaseIneq(ineq), BaseBelong([args[0].var, '\\in', z_inter]))
        self.steps += stepsolver2.steps
        self.label.update(stepsolver2.label)
        return self


class DanDiaoXingQiuCan005(BaseFunction):
    def solver(self, *args):
        """
        :param args:
            BaseSinFunc({"var": "x", "expression": "cos(2*x)+a*sin(x)", "type": "", "name": "f"})
            BaseInter(["(", "(pi)/(6)", "(pi)/(3)", ")"])
        :return: BaseVariable
        备注:第二个为单调递减区间
        """
        assert len(args) == 2
        z_inter = args[1].interval
        self.steps.append(["", "求导,得"])
        stepsolver1 = HanShuDaoShuYunSuan().solver(BaseFunc({"var": args[0].var,
                                                             "name": args[0].name,
                                                             "type": args[0].type,
                                                             "expression": args[0].expression}))
        self.steps += stepsolver1.steps
        self.label.update(stepsolver1.label)
        daohanshu = stepsolver1.output[0].sympify()
        self.steps.append(["", "∵%s在%s上单调递减" % (args[0].printing(), args[1].printing())])
        ineq = [daohanshu[1], "<=", S.Zero]
        self.steps.append(["", "%s在%s上恒成立" % (BaseIneq(ineq).printing(), args[1].printing())])
        stepsolver2 = HengChengLiRenYiXing().solver(BaseIneq(ineq), BaseBelong([args[0].var, '\\in', z_inter]))
        self.steps += stepsolver2.steps
        self.label.update(stepsolver2.label)
        return self


if __name__ == '__main__':
    pass
